<template>
  <div class="my-scene-box" ref="webgl"></div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import Stats from "three/examples/jsm/libs/stats.module.js";
import WebGL from "@/utils/WebGL.js";
export default {
  data() {
    return {
      scene: null, // 场景
      renderer: null, // 渲染器
      controls: null, // 轨道控制器
      camera: null, // 相机
      mesh01: null,
      mesh02: null,
      stats: null, // 性能检测
    };
  },
  mounted() {
    this.initPage();
  },
  methods: {
    initPage() {
      const width = this.$refs.webgl.clientWidth;
      const height = this.$refs.webgl.clientHeight;
      // 创建场景
      const scene = this.initScene();
      // 创建网格模型
      const mesh01 = this.initMesh01();
      const mesh02 = this.initMesh02();
      scene.add(mesh01);
      scene.add(mesh02);

      // 创建辅助坐标轴
      const AxesHelper = new THREE.AxesHelper(300);
      scene.add(AxesHelper);

      // 点光源
      const pointLight = this.initLight();
      const pointLightHelper = this.initLightHelper(pointLight); // 点光源辅助
      scene.add(pointLight);
      scene.add(pointLightHelper);
      //创建相机对象
      const k = width / height; //窗口宽高比
      const s = 300; //三维场景显示范围控制系数，系数越大，显示的范围越大
      const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
      camera.position.set(200, 500, 500); //设置相机位置
      camera.lookAt(scene.position); //设置相机方向(指向的场景对象)

      // 创建渲染器
      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(width, height); //设置渲染区域尺寸
      renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
      renderer.shadowMap.enabled = true; // 开启阴影
      renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default  定义阴影贴图类型

      this.$refs.webgl.appendChild(renderer.domElement); //body元素中插入canvas对象
      // 新增轨道控制器
      const controls = new OrbitControls(camera, renderer.domElement); //创建控件对象

      // 性能检测 FPS 显示检测
      const stats = new Stats();
      stats.domElement.style.position = "absolute";
      stats.domElement.style.left = "0px";
      stats.domElement.style.top = "0px";
      this.$refs.webgl.appendChild(stats.domElement); //目标元素中插入帧数显示

      this.controls = controls;
      this.scene = scene;
      this.renderer = renderer;
      this.camera = camera;
      this.mesh01 = mesh01;
      this.mesh02 = mesh02;
      this.stats = stats;

      this.loopRender(stats);
    },
    initScene() {
      return new THREE.Scene();
    },
    initMesh01() {
      const geometry = new THREE.BoxGeometry(100, 100, 100); //盒子模型
      const material = new THREE.MeshLambertMaterial(); // 漫反射材质
      return new THREE.Mesh(geometry, material);
    },
    initMesh02() {
      const geometry = new THREE.BoxGeometry(100, 100, 100); //盒子模型
      const material = new THREE.MeshLambertMaterial(); // 漫反射材质
      const mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(100, 0, 0);
      return mesh;
    },
    initLight() {
      // 点光源  可以设置多个点光源
      const point = new THREE.PointLight(0xffffff);
      point.position.set(400, 400, 400); //点光源位置

      return point;
    },
    initLightHelper(point) {
      const size = 10;
      // 新增点光源辅助
      const pointLight = new THREE.PointLightHelper(point, size, 0xf00);
      return pointLight;
    },
    // 浏览器WebGL兼容性判断
    webGLIsRun() {
      return new Promise((resolve, reject) => {
        // 浏览器WebGL兼容性判断
        if (!WebGL.isWebGLAvailable()) {
          const warning = WebGL.getWebGLErrorMessage();
          reject(warning);
        } else {
          resolve();
        }
      });
    },
    // 渲染函数
    loopRender() {
      // 设置相机旋转
      this.mesh01.rotateY(0.01);
      this.stats.update(); // 性能检测
      requestAnimationFrame(this.loopRender);
      this.renderer.render(this.scene, this.camera); //执行渲染操作
    },
  },
};
</script>

<style>
.my-scene-box {
  width: 90%;
  height: 500px;
  margin: 0 auto;
  border: 1px solid #000;
  position: relative;
}
</style>
